package com.zdp.seckill.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.zdp.seckill.common.exception.BusinessException;
import com.zdp.seckill.mapper.ItemStockMapperCustom;
import com.zdp.seckill.mapper.OrderInfoMapper;
import com.zdp.seckill.mapper.SequenceInfoMapper;
import com.zdp.seckill.pojo.OrderInfo;
import com.zdp.seckill.pojo.SequenceInfo;
import com.zdp.seckill.pojo.vo.ItemModel;
import com.zdp.seckill.pojo.vo.OrderModel;
import com.zdp.seckill.pojo.vo.UserModel;
import com.zdp.seckill.service.ItemService;
import com.zdp.seckill.service.OrderService;
import com.zdp.seckill.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @author sesshomaru
 * @date 2021/6/19 14:46
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private ItemService itemService;

    @Autowired
    private UserService userService;

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private SequenceInfoMapper sequenceInfoMapper;

    @Transactional
    @Override
    public OrderModel createOrder(Integer userId, Integer itemId, Integer promoId, Integer amount) {
        // 1.校验下单状态； 1.下单商品是否存在 2.用户是否合法 3.购买数量是否正确 4.获取商品是否存在活动
        ItemModel itemModel = itemService.getItemById(itemId);
        if (itemModel == null) {
            throw new BusinessException("商品信息不存在");
        }
        UserModel user = userService.getUserById(userId);
        if (user == null) {
            throw new BusinessException("用户信息不存在");
        }
        if (amount <= 0 || amount >= 99) {
            throw new BusinessException("购买数量不正确");
        }

        // 校验秒杀活动信息
        if (promoId != null) {
            // 1.校验对应秒杀活动是否存在这个下单的商品
            if (promoId != itemModel.getPromoModel().getId()) {
                throw new BusinessException("活动信息有误");
                // 2. 校验活动是否正在进行
            } else if (itemModel.getPromoModel().getStatus() != 2){
                throw new BusinessException("活动信息有误, 活动还未开始");
            }
        }

        // 2.落单冻结库存
        boolean result = itemService.decreaseStock(itemId, amount);
        if (!result) {
            throw new BusinessException("库存不足");
        }

        // 3.订单入库
        OrderModel orderModel = new OrderModel();
        orderModel.setUserId(userId);
        orderModel.setItemId(itemId);
        orderModel.setAmount(amount);
        // 添加活动信息
        orderModel.setPromoId(promoId);
        if (promoId != null) {
            // 该商品存在对应的活动则替换单价为活动价格
            orderModel.setItemPrice(itemModel.getPromoModel().getPromoItemPrice());
        } else {
            // 原价
            orderModel.setItemPrice(itemModel.getPrice());
        }
        // 单价 * 数量 = 订单金额
        orderModel.setOrderPrice(orderModel.getItemPrice().multiply(new BigDecimal(amount)));

        OrderInfo orderInfo = convertFromOrderModel(orderModel);
        // 添加自定义的订单id
        orderInfo.setId(generateOrderNo());
        // 生成订单流水号
        orderInfoMapper.insert(orderInfo);

        // 增加对应的商品销量
        itemService.increaseSales(itemId, amount);

        // 4.返回前端
        return orderModel;
    }

    // 为了保证获取订单id的全局唯一这里需要单独的在一个事务里面执行，避免因为外部调用的方法中发生异常导致订单号生成后又回滚掉
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public String generateOrderNo() {
        //订单号有16位
        StringBuilder stringBuilder = new StringBuilder();
        //前8位为时间信息，年月日
        LocalDateTime now = LocalDateTime.now();
        String nowDate = now.format(DateTimeFormatter.ISO_DATE).replace("-","");
        stringBuilder.append(nowDate);

        //中间6位为自增序列
        //获取当前sequence
        int sequence = 0;
        // 这里需要加for update锁
        SequenceInfo sequenceInfo = sequenceInfoMapper.getSequenceByName("order_info");
        sequence = sequenceInfo.getCurrentValue();
        // 递增步长
        sequenceInfo.setCurrentValue(sequence + sequenceInfo.getStep());
        UpdateWrapper<SequenceInfo> sequenceInfoUpdateWrapper = new UpdateWrapper<>();
        sequenceInfoUpdateWrapper.eq("name", "order_info");
        sequenceInfoMapper.update(sequenceInfo, sequenceInfoUpdateWrapper);

        // 拼接它凑足6位
        String sequenceStr = String.valueOf(sequence);
        // 补充当前还缺多少位
        for(int i = 0; i < 6-sequenceStr.length();i++){
            stringBuilder.append(0);
        }
        stringBuilder.append(sequenceStr);

        //最后2位为分库分表位,暂时写死
        stringBuilder.append("00");

        return stringBuilder.toString();
    }

    private OrderInfo convertFromOrderModel(OrderModel orderModel) {
        if (orderModel == null) {
            return null;
        }
        OrderInfo orderInfo = new OrderInfo();
        BeanUtils.copyProperties(orderModel, orderInfo);
        return orderInfo;
    }
}
